/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package com.apps.controllers;

import com.jcraft.jsch.Channel;
import com.jcraft.jsch.JSch;
import com.jcraft.jsch.Session;
import com.jcraft.jsch.UIKeyboardInteractive;
import com.jcraft.jsch.UserInfo;
import java.util.Scanner;
import sun.awt.windows.ThemeReader;

/**
 *
 * @author ARIJIT PAL
 */
public class ShellController implements Runnable{

    private Channel channel;
    private Session session;
    private CustomInputStream ins;

    private String host;
    private String port;
    private String user;
    private String passwd;
    private boolean closeFlag;
    private String accID;
    private boolean activeFlag;

    /*public ShellController(){
        channel = null;
        session = null;
        ins = null;
        this.host = this.port = this.user = this.passwd = null;
        closeFlag = false;
    }*/

    public ShellController(String accID, String host, String port, String user, String passwd){
        channel = null;
        session = null;
        ins = null;
        this.host = host;
        this.port = port;
        this.user = user;
        this.passwd = passwd;
        closeFlag = false;
        this.accID = accID;
        activeFlag = true;
    }
    
    public String getHost() {
        return host;
    }

    public String getPort() {
        return port;
    }
    
    public boolean getShellStatus(){
        if (channel == null || channel.isClosed()) {
            return false;
        }
        return true;
    }

    public String getAccID(){
        return accID;
    }

    public boolean isActiveFlag() {
        return activeFlag;
    }

    public void setActiveFlag(boolean activeFlag) {
        this.activeFlag = activeFlag;
    }
    
    public boolean getActiveFlag() {
        return this.activeFlag;
    }
    
    public void openShell() throws Exception{
        try{
            System.out.println("Opening shell : "+host+":"+port);
            closeFlag = true;
            if(host != null && port != null && user != null && passwd != null){
                /*if(session == null){*/
                    setConig(host, port, user, passwd);
                    startShell();
                /*}else{
                    if(channel == null){
                        startShell();
                    }
                }*/
                Thread th = new Thread(this);
                closeFlag = false;
                th.start();
            }else{
                System.out.println("Please setup the controller first!!!");
            }
        }catch(Exception ex){
            Thread th = new Thread(this);
            session = null;
            channel = null;
            closeFlag = false;
            try{Thread.sleep(10000);}catch(Exception ee){}
            th.start();
            ex.printStackTrace();
        }
    }

    public void closeShell(){
        closeFlag = true;
        try{
            executeCmd("logout");
            channel.disconnect();
            session.disconnect();
        }catch(Exception ex){
            channel = null;
            session = null;
        }
    }

    @Override
    public void run(){
        System.out.println("Thread Started: "+host+":"+port);
        try{
            while(true){
                if(session == null){
                    try{Thread.sleep(2000);}catch(Exception ee){}
                    break;
                }
                if(channel == null){
                    try{Thread.sleep(2000);}catch(Exception ee){}
                    continue;
                }
                if(channel.isClosed()){
                    System.out.println("exit-status: "+channel.getExitStatus());
                    break;
                }
                try{Thread.sleep(2000);}catch(Exception ee){}
            }
            if(!closeFlag)
                openShell();
        }catch(Exception ex){
            ex.printStackTrace();
            try{Thread.sleep(2000);}catch(Exception ee){}
            if(!closeFlag)
                run();
        }
    }

    private void setConig(String host, String port, String user, String passwd){
        session = null;
        channel = null;
        try{
          JSch jsch=new JSch();
          System.out.println("Start Shell Config for "+host+":"+port+"@"+user);

          session=jsch.getSession(user, host, Integer.valueOf(port));
          session.setPassword(passwd);

          UserInfo ui = new MyUserInfo();
          session.setUserInfo(ui);

        }catch(Exception ex){
            ex.printStackTrace();
        }
    }

    private boolean startShell() throws Exception{
        try{
          session.connect(30000);   // making a connection with timeout.

          channel=session.openChannel("shell");

          //InputStream in=channel.getInputStream();

          ins = new CustomInputStream(30,channel);
          channel.setInputStream(/*System.in*/ins);

          channel.connect();//connecting to the shell channel
          ins.startCmdOut();//start output controller
          executeCmd("\n\n\n\n\n");//this is for initial stuff
          return true;
        }catch(Exception ex){
            ex.printStackTrace();
            throw ex;
        }
        //return false;
    }

    public String executeCmdRT(String command, String endPattern) throws Exception{
        return ins.getOutput(command, 0, endPattern);
    }

    public String executeCmdRT(String command, String endPattern, int timeOut) throws Exception{
        return ins.getOutput(command, timeOut, endPattern);
    }

    public void executeCmd(String command){
        ins.setCommand(command);
    }
    
    //class for interactive method
    private static class MyUserInfo
                          implements UserInfo, UIKeyboardInteractive{
    public String getPassword(){ return null; }
    public boolean promptYesNo(String str){ System.out.println(str);
          return true; }
    public String getPassphrase(){ return null; }
    public boolean promptPassphrase(String message){ return false; }
    public boolean promptPassword(String message){ return false; }
    public void showMessage(String message){ System.out.println(message); }
    public String[] promptKeyboardInteractive(String destination,
                                              String name,
                                              String instruction,
                                              String[] prompt,
                                              boolean[] echo){
      return null;
    }
  }

    public static void main(String[] args) throws Exception{
        ShellController ctrl = new ShellController("1","shellmix.com", "22", "arijitpal", "pa00word");
        //ShellController ctrl = new ShellController("1","localhost", "22", "sshuser", "test123");
        ctrl.openShell();
        Scanner scn = new Scanner(System.in);
        String line ="";
        while(!(line = scn.nextLine()).equalsIgnoreCase("quit")){
            System.out.println(line+"> "+ctrl.executeCmdRT(line.split("@")[0], line.split("@")[1]));
        }
        ctrl.closeShell();
    }

}
